package com.example.demo.annotation;


import com.alibaba.fastjson.JSON;
import com.example.demo.po.LogPO;
import com.example.demo.service.LogService;
import com.example.demo.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

@Component
@Aspect
@Slf4j
public class Printlogs {

    @Autowired
    private LogService logService;

    @Pointcut("@annotation(com.example.demo.annotation.PrintLog)")
    public void pointcut(){

    }

    @Around("pointcut()")
    public Object printLogs(ProceedingJoinPoint joinPoint) throws Throwable{
        Object proceed;
        LogPO logPO = new LogPO();
        try {
            proceed = dealLogPO(joinPoint, logPO);
            logPO.setFlag("1");
            logPO.setFalseInfo("success");
            logService.saveLogs(logPO);
        }catch (Exception e){
            logPO.setFlag("2");
            logPO.setFalseInfo(e.getMessage());
            logService.saveLogs(logPO);
            e.printStackTrace();
            log.info("error={}",e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
        return proceed;
    }

    public Object dealLogPO(ProceedingJoinPoint joinPoint,LogPO logPO) throws Throwable{
        Object proceed = null;
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
        Object[] args = joinPoint.getArgs();
        StringBuilder par = new StringBuilder();
        for (Object tmp : args) {
            par.append(tmp.toString());
            par.append(",");
        }
        HttpServletRequest request = requestAttributes.getRequest();
        String requestURI = requestAttributes.getRequest().getRequestURI();
        Class<?> aClass = joinPoint.getTarget().getClass();
        String name = joinPoint.getSignature().getName();
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Class<?>[] parameterTypes = methodSignature.getMethod().getParameterTypes();
        Method method = aClass.getDeclaredMethod(name,parameterTypes);
        PrintLog annotation = method.getAnnotation(PrintLog.class);
        if (annotation != null) {
            String value = annotation.value();
            log.info("接口--方法：{}[{}]--[{}]>>>>方法开始执行>>>>", declaringTypeName,requestURI,value);
            String parms = null;
            if (par.toString().contains(",")){
                parms = par.toString().substring(0,par.toString().length()-1);
            }
            log.info("传入参数：{}", parms);
            logPO.setMethods(requestURI);
            logPO.setModule(declaringTypeName);
            logPO.setRequestParams(parms);
            logPO.setIp(IpUtils.getIP(request));
            Type genericReturnType = method.getGenericReturnType();
            if (genericReturnType != null) {
                proceed = joinPoint.proceed();
                logPO.setResponseParams(JSON.toJSONString(proceed));
                log.info("该方法返回值为：{}", proceed);
            }
            log.info("接口--方法：{}[{}]--[{}]>>>>方法执行结束>>>>", declaringTypeName,requestURI,value);
        }
        return proceed;
    }

}
